#ifndef GRAPHIC_DATA_H
#define GRAPHIC_DATA_H

#include "../../editors/items/abstractlinegraphicitem.h"

#include <graphicdatamodel.h>
#include <idocumentdata.h>
#include <ieditor.h>
#include <palette.h>

#include <QtGui/QGraphicsScene>

namespace core
{
class IGraphicEditorItem;
}

namespace gui
{
class RectGraphicItem;
}

namespace swp
{
class AddConnectionCommand;
class RemoveConnectionCommand;

class GraphicData : public QGraphicsScene, public core::IDocumentData,
    public core::GraphicDataModel
{
    Q_OBJECT

public:
    GraphicData();
    virtual ~GraphicData();

    // IDocumentData
    Type type() const;

    void setConnectionData(const core::ConnectionData &data);
    const core::ConnectionData& connectionData() const;

    bool supportsConnections() const;
    QList<core::ConnectionData> connections(
        const core::IEditorItem* item) const;
    virtual void clearData(const QList<core::IEditorItem* >& preserve =
        QList<core::IEditorItem* >());
    QList<core::ConnectionData> connections() const;
    core::ConnectionData connectionData(
        core::IGraphicEditorItem* connector) const;
    void makeConnection(uint connectionId, const QUuid& connector,
        const QUuid& from, const QUuid& to);

    core::IEditor::State currentState() const;
    virtual void setCurrentState(core::IEditor::State state);
    void scaleSelectionToFitContent();

    QList<core::IGraphicEditorItem* > selectedGraphicItems() const;

    void addGraphicItem(core::IGraphicEditorItem* item);
    void removeGraphicItem(core::IGraphicEditorItem* item,
        bool keepInstance = false);

    QList<core::IGraphicEditorItem* > graphicItems() const;
    const core::Palette* graphicPalette() const;

    void setGraphicPalette(const core::Palette* const palette);

    bool inUnfinishedConnection() const;
    void cancelUnfinishedConnection(bool completeReset = false);
    void removeLastConnectorAnchor();

    void emitDataChanged();

    void snapCursor(const QPointF& point);
    QPointF snapToGrid(QGraphicsItem* item, const QPointF& oldPos,
        const QPointF& newPos, bool force = false,
        core::IGraphicEditorItem* gItem = 0, bool ignoreFlag = false);
    bool snapToGridEnabled() const;
    void setSnapToGrid(bool enabled);
    void addSnapToGridException(int type);

    void expandIfNeeded(QGraphicsItem* item, const QPointF& newPos);

    void registerForResizeNotification(core::IGraphicEditorItem* item);
    void unregisterForResizeNotification(core::IGraphicEditorItem* item);

    void setIgnoreSnapFlag(bool ignoreSnapFlag);

    void selectAll();
    void unselectAll();

    void duplicateSelectedItem();

protected:
    virtual void mousePressEvent(QGraphicsSceneMouseEvent* event);
    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* event);
    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);

    void drawBackground(QPainter* painter, const QRectF& rect);

private:
    void resetConnectionData(bool completeReset);
    void addConnection(const core::IEditorItem* item,
        const core::ConnectionData& data);
    void removeConnection(const core::IEditorItem* item,
        const core::ConnectionData& data);

    inline qreal round(qreal val, int step) {
       int tmp = int(val) + step /2;
       tmp -= tmp % step;
       return qreal(tmp);
    }

signals:
    void dataChanged();
    void editorItemSelectionChanged(core::IGraphicEditorItem* item);

private slots:
    void handleSelectionChange();

protected:
    friend class RemoveGraphicItemCommand;
    friend class AddConnectionCommand;
    friend class RemoveConnectionCommand;
    friend class ChangeTypeCommand;
    bool m_previousSelfConnect;
    bool m_snapToGrid;
    bool m_ignoreSnapFlag;
    bool m_inRangeSelect;
    qreal m_gridStep;
    QPen m_gridPen;
    core::Palette* m_palette;
    core::IEditor::State m_state;
    core::ConnectionData m_connectionData;
    AbstractLineGraphicItem* m_potentialConnection;
    gui::RectGraphicItem* m_rangeSelectRect;
    QList<core::ConnectionData> m_allConnections;
    QHash<const core::IEditorItem*,
        QList<core::ConnectionData> > m_connections;
    QHash<QUuid, core::IEditorItem*> m_idToInstanceMapping;
    QList<int> m_snapToGridExpcetions;
    QList<core::IGraphicEditorItem*> m_registeredForResizeNotification;
    QPointF m_rangeSelectStartPoint;
};

} // namespace swp

#endif
